A Good Use For Base 64 Encoding: Data URIs
First, WordPress plugin authors: Please don’t do this.
if ( isset($_GET['resource']) && !empty($_GET['resource']) ) {
$resources = array(
'icon1.png' => '... base 64 encoded code ...',
'icon2.png' => '... base 64 encoded code ...',
);
if ( array_key_exists($_GET['resource'], $resources) ) {
$content = base64_decode($resources[ $_GET['resource'] ]);
header('Content-Length: '.strlen($content));
header('Content-Type: image/png');
echo $content;
exit;
}
}
I’ve seen a few different versions of this, and while the idea is nice, this is really the wrong way to go about it.
The idea is to include small icons or images in the plugin file itself, instead of as separate files. This sort of code then lets you reference them by calling a URL of ?resource=icon1.png or whatever. When that resource variable is detected, the plugin kicks in and serves up the image instead of the site.
Advantages to this sort of thing:
- No need for extra icon files
Disadvantages to this sort of thing:
- Now every http request to get an icon file on your admin page results in loading up the WordPress code, causing extra CPU usage.
Here’s a better way. It’s called the Data URI.
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />
Here’s that code in action, right here:
Why this is better:
- Same benefits as before, no need for extra icon files
- No extra CPU load from loading WordPress to get that icon file
- No extra HTTP requests at all, in fact, since the data for the tiny icon is contained right there in the code
Disadvantage:
- Doesn’t work in IE7. You can work around this by detecting IE7 and serving up the image separately, if you really want. Or you can just ignore it like most people do. Seriously. IE7 is insecure (link, link) and nobody should be using it, anywhere. WordPress itself will probably drop IE7 support in the admin in the next couple of versions.
So use Data URIs for small images (under 32KB in size). They’re fast and easy. They’re an idea whose time has come.
This method is most popular for mobile sites where IE7 isn’t even an issue. For viewing on a desktop, I prefer image sprites.
The problem I have with image sprites is that the whole thing is a sort of “hack”. It requires a specially crafted image along with CSS positioning weirdness to make it work. I grant you that it is a helpful technique, but it’s not exactly “pure” in my view. We shouldn’t have to resort to workarounds to make things faster or more efficient.
That said, image sprites are handy and can be very useful if you’re trying to reduce http requests for a site.
I’ve been watching data URIs for awhile and I’m still not 100% where the trade off lines are. One of the downsides to base64 encoding for instance is that it increases the size by roughly 33%. But then you have to wonder how much HTTP compression would make up for that. I wonder if anyone has done serious testing and benchmarks around this.
Yeah, this mainly makes sense for smaller images where the overhead of setting up the extra HTTP connection isn’t worth it. For the specific cases I’ve seen in plugins doing this sort of thing, these images are tiny. Few hundred bytes.
One disadvantage to the data uri scheme is that you don’t gain any browser caching benefits. You’re always sending this data with the page. But for a couple hundred bytes, it doesn’t make a heck of a lot of difference. For a few K or more, it might.
Otto,
If someone was to do this for their wordpress theme option page and then get it listed on wordpress.org it would get rejected right?
No, shouldn’t be. It doesn’t violate any of the normal checks. Should go through just fine. Might get some feedback if the reviewer is unaware of the data URI scheme, but it’d be fine, I think.
This is awesome!!
Hello Otto,
thank you for this page. I am looking for clues, why my base64 image is not working. The exemple given “Here’s that code in action, right here: Red dot” do not work either. Have you got any idea, why ?
If you use the plugin Jetpack, the lazy loading feature breaks it.